package com.wlyuan.open.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wlyuan.mybatis.query.PageUtils;
import com.wlyuan.mybatis.query.QueryUtils;
import com.wlyuan.mybatis.utils.RepositoryUtils;
import com.wlyuan.open.dao.entity.OpenApiDO;
import com.wlyuan.open.dao.mapper.OpenApiMapper;
import com.wlyuan.open.domain.api.OpenApi;
import com.wlyuan.open.domain.api.OpenApiPattern;
import com.wlyuan.open.domain.api.respository.OpenApiRepository;
import com.wlyuan.open.domain.api.valueobj.OpenApiId;
import com.wlyuan.open.dto.api.OpenApiFilterDTO;
import com.wlyuan.open.infrastructure.config.OpenApiProperties;
import com.wlyuan.open.infrastructure.converter.OpenApiConverter;
import com.wlyuan.utils.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yuanzheng
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OpenApiRepositoryImpl implements OpenApiRepository {
    private final OpenApiMapper openApiMapper;
    private final OpenApiProperties openApiProperties;

    @Override
    public OpenApi ofId(@NotNull OpenApiId openApiId) {
        return OpenApiConverter.convert(openApiMapper.selectById(openApiId.getId()));
    }

    @Override
    public OpenApiId save(OpenApi openApi) {
        var apiDO = RepositoryUtils.save(openApiMapper,
                OpenApiConverter::convert,
                openApi, openApi.getId());

        openApi.setId(new OpenApiId(apiDO.getId()));
        return openApi.getId();
    }

    @Override
    public void remove(OpenApiId openApiId) {
        openApiMapper.deleteById(openApiId.getId());
    }

    @Override
    public List<OpenApi> list(Collection<OpenApiId> openApiIds) {
        if (CollectionUtils.isEmpty(openApiIds)) {
            return Collections.emptyList();
        }
        List<Long> ids = openApiIds.stream().map(OpenApiId::getId).collect(Collectors.toList());
        LambdaQueryWrapper<OpenApiDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(OpenApiDO::getId, ids).orderByDesc(OpenApiDO::getSort).orderByDesc(OpenApiDO::getId);
        return OpenApiConverter.convert(openApiMapper.selectList(queryWrapper));
    }

    @Override
    public Page<OpenApiId> search(OpenApiFilterDTO filter) {
        QueryWrapper<OpenApiDO> query = QueryUtils.build(openApiProperties.getSearch().getRules(), filter);
        query.lambda().orderByDesc(OpenApiDO::getSort).orderByDesc(OpenApiDO::getId);
        var result = openApiMapper.selectPage(PageUtils.page(filter), query);
        return PageUtils.as(result, openApiDO -> new OpenApiId(openApiDO.getId()));
    }

    @Override
    public OpenApi getByUrl(String url, String method) {
        LambdaQueryWrapper<OpenApiDO> query = new LambdaQueryWrapper<>();
        query.eq(OpenApiDO::getUrl, url).eq(OpenApiDO::getMethod, method.toUpperCase());
        return OpenApiConverter.convert(openApiMapper.selectOne(query));
    }

    @Override
    public List<OpenApi> ofPattern(OpenApiPattern pattern) {
        LambdaQueryWrapper<OpenApiDO> query = new LambdaQueryWrapper<>();
        query.like(OpenApiDO::getName, pattern.getName());
        return OpenApiConverter.convert(openApiMapper.selectList(query));
    }

    @Override
    public List<OpenApi> ofAll() {
        return OpenApiConverter.convert(openApiMapper.selectList(new LambdaQueryWrapper<>()));
    }
}
